package cn.wolfcode.p2p.business.service.impl;

import cn.wolfcode.p2p.base.domain.Account;
import cn.wolfcode.p2p.base.domain.BaseDomain;
import cn.wolfcode.p2p.base.domain.LoginInfo;
import cn.wolfcode.p2p.base.domain.UserInfo;
import cn.wolfcode.p2p.base.exception.DisplayableException;
import cn.wolfcode.p2p.base.qo.BidRequestQueryObject;
import cn.wolfcode.p2p.base.qo.QueryObject;
import cn.wolfcode.p2p.base.service.IAccountService;
import cn.wolfcode.p2p.base.service.ILoginInfoService;
import cn.wolfcode.p2p.base.service.IUserInfoService;
import cn.wolfcode.p2p.base.util.BitStateUtil;
import cn.wolfcode.p2p.base.util.Constants;
import cn.wolfcode.p2p.base.util.UserContext;
import cn.wolfcode.p2p.business.domain.*;
import cn.wolfcode.p2p.business.mapper.BidRequestMapper;
import cn.wolfcode.p2p.business.service.*;
import cn.wolfcode.p2p.business.util.CalculatetUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.font.BidiUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Service@Transactional
public class BidRequestServiceImpl implements IBidRequestService {
    @Autowired
    private BidRequestMapper bidRequestMapper;
    @Autowired
    private IUserInfoService userInfoService;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IBidRequestAuditHistoryService bidRequestAuditHistoryService;
    @Autowired
    private IBidService bidService;
    @Autowired
    private IAccountFlowService accountFlowService;
    @Autowired
    private ISystemAccountService systemAccountService;
    @Autowired
    private ISystemAccountFlowService systemAccountFlowService;
    @Autowired
    private IPaymentScheduleService paymentScheduleService;
    @Autowired
    private IPaymentScheduleDetailService paymentScheduleDetailService;

    @Override
    public int save(BidRequest bidRequest) {
        return bidRequestMapper.insert(bidRequest);
    }

    @Override
    public int update(BidRequest bidRequest) {
        int count = bidRequestMapper.updateByPrimaryKey(bidRequest);
        if (count == 0) {
            System.out.println("乐观锁异常,bidRequestId:"+bidRequest);
            throw new DisplayableException("系统繁忙,请稍后再试");
        }
        return count;
    }

    @Override
    public BidRequest get(Long id) {
        return bidRequestMapper.selectByPrimaryKey(id);
    }

    @Override
    public List<BidRequest> queryMainData() {
        PageHelper.startPage(1,5);
        BidRequestQueryObject qo = new BidRequestQueryObject();
        //招标中,还款中,已还清
        qo.setStates(new int[]{Constants.BIDREQUEST_STATE_BIDDING, Constants.BIDREQUEST_STATE_PAYING_BACK, Constants.BIDREQUEST_STATE_COMPLETE_PAY_BACK});
        qo.setOrderByCondition(" b.bidRequestState asc"); //招标中,还款中,已还清 顺序排列
        List<BidRequest> bidRequests = bidRequestMapper.queryData(qo);
        return bidRequests;
    }

    @Override
    public List<BidRequest> queryPendingBidRequestListInOneHour() {
        Date now = new Date();
        Date endDate = DateUtils.addHours(now, 1);
        endDate = DateUtils.setMinutes(endDate, 0);
        endDate = DateUtils.setSeconds(endDate, 0);
        return bidRequestMapper.queryPendingBidRequestListInOneHour(endDate, Constants.BIDREQUEST_STATE_PUBLISH_PENDING); //设置最近一小时发标,且状态处于待发标
    }

    @Override
    public List<BidRequest> queryPassDisableDateBidRequestListInOneHour() {
        Date now = new Date();
        Date endDate = DateUtils.addHours(now, 1);
        endDate = DateUtils.setMinutes(endDate, 0);
        endDate = DateUtils.setSeconds(endDate, 0);
        return bidRequestMapper.queryPassDisableDateBidRequestListInOneHour(endDate, Constants.BIDREQUEST_STATE_BIDDING);
    }

    @Override
    public List<BidRequest> queryPublishPendngBidRequests() {
        BidRequestQueryObject qo = new BidRequestQueryObject();
        qo.setBidRequestState(Constants.BIDREQUEST_STATE_PUBLISH_PENDING); //待发标
        List<BidRequest> bidRequests = bidRequestMapper.queryData(qo);
        return bidRequests;
    }

    @Override
    public void audit(Long id, Integer state, Date publishTime, String remark) {
        //通过Id获取借款对象,处于待审核状态
        BidRequest bidRequest = this.get(id);
        if (bidRequest != null && bidRequest.getBidRequestState() == Constants.BIDREQUEST_STATE_APPLY) {
            createBidRequestAuditHistory(state, remark, bidRequest,BidRequestAuditHistory.TYPE_PUBLISH);
            //审核通过
            if (state == BidRequestAuditHistory.STATE_PASS) {
                if (publishTime == null) {
                    //不是定时发标
                    //修改借款对象属性
                    //修改借款的状态 ==> 招标中
                    bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_BIDDING);
                    //设置发布时间,招标截止时间,风控意见
                    bidRequest.setPublishTime(new Date());
                } else {
                    //定时发标
                    //修改借款对象属性
                    //修改借款的状态 ==> 待发布
                    bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_PUBLISH_PENDING);
                    //设置发布时间,招标截止时间(发布时间+招标天数),风控意见
                    bidRequest.setPublishTime(publishTime);
                }
                bidRequest.setDisableDate(DateUtils.addDays(bidRequest.getPublishTime(), bidRequest.getDisableDays()));
                bidRequest.setNote(remark);
            } else {
                //审核失败
                //修改借款的状态 ==> 发标审核拒绝
                bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_PUBLISH_REFUSE);
                //借款人属性变化
                UserInfo createUser = userInfoService.get(bidRequest.getCreateUser().getId());
                //移除借款申请状态码
                createUser.removeState(BitStateUtil.HAS_BIDREQUEST_PROCESS);
                userInfoService.update(createUser);
            }
            this.update(bidRequest);
        }
    }

    private void createBidRequestAuditHistory(Integer state, String remark, BidRequest bidRequest, int auditType) {
        //创建借款审核对象(审核人,审核时间,审核状态,审核备注)
        BidRequestAuditHistory brah = new BidRequestAuditHistory();
        brah.setAuditType(auditType); //审核状态
        brah.setBidRequestId(bidRequest.getId()); //借款人Id
        brah.setApplier(bidRequest.getCreateUser()); //申请人
        brah.setApplyTime(bidRequest.getApplyTime()); //申请时间
        brah.setAuditor(UserContext.getCurrent()); //审核人
        brah.setAuditTime(new Date()); //审核时间
        brah.setState(state); //审核状态
        brah.setRemark(remark); //审核备注
        bidRequestAuditHistoryService.save(brah);
    }

    @Override
    public void apply(BidRequest bidRequest) {
        UserInfo userInfo = userInfoService.getCurrent();
        //用户是否有借款的条件(实名认证,基本信息认证,视频认证)
        //用户没有正在借款的流程
        if (!userInfo.getCanBorrow() || userInfo.getHasBidRequestProcess()) {
            throw new DisplayableException("非法操作");
        }
        Account account = accountService.getCurrent();
        //借款金额 [最小系统借款金额, 剩余信用额度]
        //借款利息 [最小利息, 最大利息]
        //最小投标 [系统最小投标]
        if (bidRequest.getBidRequestAmount().compareTo(Constants.BORROW_AMOUNT_MIN) >= 0
                && bidRequest.getBidRequestAmount().compareTo(account.getRemainBorrowLimit()) <= 0
                && bidRequest.getCurrentRate().compareTo(Constants.RATE_MIN) >= 0
                && bidRequest.getCurrentRate().compareTo(Constants.RATE_MAX) <= 0
                && bidRequest.getMinBidAmount().compareTo(Constants.BID_AMOUNT_MIN) >= 0
                ) {
            BidRequest br = new BidRequest();
            br.setApplyTime(new Date());
            br.setBidRequestAmount(bidRequest.getBidRequestAmount());
            br.setBidRequestState(Constants.BIDREQUEST_STATE_APPLY); //待审核
            br.setBidRequestType(Constants.BIDREQUEST_TYPE_NORMAL); //普通信用标
            br.setCreateUser(UserContext.getCurrent()); //借款人
            br.setCurrentRate(bidRequest.getCurrentRate()); //年化利率
            br.setDescription(bidRequest.getDescription()); //借款描述
            br.setDisableDays(bidRequest.getDisableDays()); //招标天数
            br.setMinBidAmount(bidRequest.getMinBidAmount()); //最小投标金额
            br.setMonthes2Return(bidRequest.getMonthes2Return());//借款期限
            br.setReturnType(Constants.RETURN_TYPE_MONTH_INTEREST_PRINCIPAL);//等额本息
            br.setTitle(bidRequest.getTitle());//借款标题
            //借款总利息
            br.setTotalRewardAmount(CalculatetUtil.calTotalInterest(br.getReturnType(),br.getBidRequestAmount(),br.getCurrentRate(),br.getMonthes2Return()));
            //保存
            this.save(br);
            //添加状态
            userInfo.addState(BitStateUtil.HAS_BIDREQUEST_PROCESS); //正在借款的流程申请
            userInfoService.update(userInfo);
        } else {
            throw new DisplayableException("非法操作");
        }
    }

    @Override
    public void expApply(BidRequest bidRequest) {
        Account account = accountService.getCurrent();
        //借款金额 [最小系统借款金额, xxx]
        //最小投标 [系统最小投标]
        if (bidRequest.getBidRequestAmount().compareTo(Constants.BORROW_AMOUNT_MIN) >= 0
                && bidRequest.getMinBidAmount().compareTo(Constants.BID_AMOUNT_MIN) >= 0
                ) {
            BidRequest br = new BidRequest();
            br.setApplyTime(new Date());
            br.setBidRequestAmount(bidRequest.getBidRequestAmount());
            br.setBidRequestState(Constants.BIDREQUEST_STATE_APPLY); //待审核
            br.setBidRequestType(Constants.BIDREQUEST_TYPE_EXP); //体验标
            br.setCreateUser(UserContext.getCurrent()); //借款人
            br.setCurrentRate(bidRequest.getCurrentRate()); //年化利率
            br.setDisableDays(bidRequest.getDisableDays()); //招标天数
            br.setMinBidAmount(bidRequest.getMinBidAmount()); //最小投标金额
            br.setMonthes2Return(bidRequest.getMonthes2Return());//借款期限
            br.setReturnType(Constants.RETURN_TYPE_MONTH_INTEREST_PRINCIPAL);//等额本息
            br.setTitle(bidRequest.getTitle());//借款标题
            //借款总利息
            br.setTotalRewardAmount(CalculatetUtil.calTotalInterest(br.getReturnType(),br.getBidRequestAmount(),br.getCurrentRate(),br.getMonthes2Return()));
            //保存
            this.save(br);
        } else {
            throw new DisplayableException("非法操作");
        }
    }

    @Override
    public PageInfo queryPage(QueryObject qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List result = bidRequestMapper.queryData(qo);
        return new PageInfo(result);
    }

    @Override
    public void bid(Long bidRequestId, BigDecimal amount) {
        //1.需要哪些判断
        //查询出借款对象,处于投标状态
        BidRequest bidRequest = this.get(bidRequestId);
        if (bidRequest != null && bidRequest.getBidRequestState() == Constants.BIDREQUEST_STATE_BIDDING) {
            //借款对象不是登录的用户
            //投标数目 [系统设置最小投标, min(账户可用金额,剩余投标金额)]
            Account account = accountService.getCurrent();
            if (!bidRequest.getCreateUser().getId().equals(UserContext.getCurrent().getId())
                    &&amount.compareTo(bidRequest.getMinBidAmount())>=0
                    &&amount.compareTo(account.getUsableAmount().min(bidRequest.getRemainAmount()))<=0
                    ) {
                //2.借款对象修改 投标个数bidCount+1, 当前已投金额 currentSum= 原来的+ amount
                bidRequest.setBidCount(bidRequest.getBidCount()+1);
                bidRequest.setCurrentSum(bidRequest.getCurrentSum().add(amount));
                //3.创建投标对象
                Bid bid = new Bid();
                bid.setActualRate(bidRequest.getCurrentRate());
                bid.setAvailableAmount(amount);
                bid.setBidRequestId(bidRequestId);
                bid.setBidRequestTitle(bidRequest.getTitle());
                bid.setBidUser(UserContext.getCurrent());
                bid.setBidTime(new Date());
                bid.setBidRequestState(bidRequest.getBidRequestState());
                bidService.save(bid);
                //4.投资人账户可用金额减少,冻结金额增加
                account.setUsableAmount(account.getUsableAmount().subtract(amount));
                account.setFreezedAmount(account.getFreezedAmount().add(amount));
                accountService.update(account);
                //5.生成投标流水
                accountFlowService.createBidFlow(account, amount);
                //6.判断借款是否投满了 currentSum=bidRequestAmount
                if (bidRequest.getCurrentSum().compareTo(bidRequest.getBidRequestAmount()) ==0) {
                    //如果投满了,借款对象状态改成满标一审
                    //投标中的借款状态改成满标一审
                    bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_APPROVE_PENDING_1);
                    bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_APPROVE_PENDING_1);
                }
                this.update(bidRequest);
            } else {
                throw new DisplayableException("非法操作");
            }
        }
    }

    @Override
    public void audit1(Long id, Integer state, String remark) {
        //根据id获取借款对象,处于满标一审状态
        BidRequest bidRequest = this.get(id);
        if (bidRequest != null && bidRequest.getBidRequestState() == Constants.BIDREQUEST_STATE_APPROVE_PENDING_1) {
            //创建审核历史对象
            createBidRequestAuditHistory(state, remark, bidRequest,BidRequestAuditHistory.TYPE_AUDIT1);
            //如果审核通过
            if (state == BidRequestAuditHistory.STATE_PASS) {
                //借款对象和投标人对象中的借款状态改成满标二审
                bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_APPROVE_PENDING_2);
                bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_APPROVE_PENDING_2);
            } else {
                auditReject(bidRequest);

            }
            this.update(bidRequest);
        }
    }

    private void auditReject(BidRequest bidRequest) {
        //如果审核失败
        //借款对象和投标人对象中的借款状态改成满标拒绝
        bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_REJECTED);
        bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_REJECTED);
        //对于投资人
        Account bidUserAccount;
        Map<Long, Account> accountMap = new HashMap<Long, Account>();
        Long bidUserId;
        for (Bid bid : bidRequest.getBids()) {
            bidUserId = bid.getBidUser().getId();
            bidUserAccount = accountMap.get(bidUserId);
            if (bidUserAccount == null) {
                bidUserAccount = accountService.get(bid.getBidUser().getId());
                accountMap.put(bidUserId, bidUserAccount);
            }
            //可用金额增加,冻结减少,生成投标失败的流水
            bidUserAccount.setFreezedAmount(bidUserAccount.getFreezedAmount().subtract(bid.getAvailableAmount()));
            bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().add(bid.getAvailableAmount()));
            accountFlowService.createBidFiledFlow(bidUserAccount, bid.getAvailableAmount());
        }
        //对账户进行统一的修改
        for (Account account : accountMap.values()) {
            accountService.update(account);
        }
        //对于借款人
        //移除借款的状态码
        UserInfo createUserUserInfo = userInfoService.get(bidRequest.getCreateUser().getId());
        createUserUserInfo.removeState(BitStateUtil.HAS_BIDREQUEST_PROCESS);
        userInfoService.update(createUserUserInfo);
    }

    @Override
    public void cancelBorrow(Long bidRequestId) {
        //获取借款对象,处于招标中状态
        BidRequest bidRequest = this.get(bidRequestId);
        if (bidRequest != null && bidRequest.getBidRequestState() == Constants.BIDREQUEST_STATE_BIDDING) {
            //借款对象和投标人对象中的借款状态改成已撤销
            bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_UNDO);
            bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_UNDO);
            //对于投资人
            Account bidUserAccount;
            Map<Long, Account> accountMap = new HashMap<Long, Account>();
            Long bidUserId;
            for (Bid bid : bidRequest.getBids()) {
                bidUserId = bid.getBidUser().getId();
                bidUserAccount = accountMap.get(bidUserId);
                if (bidUserAccount == null) {
                    bidUserAccount = accountService.get(bid.getBidUser().getId());
                    accountMap.put(bidUserId, bidUserAccount);
                }
                //可用金额增加,冻结减少,生成投标失败的流水
                bidUserAccount.setFreezedAmount(bidUserAccount.getFreezedAmount().subtract(bid.getAvailableAmount()));
                bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().add(bid.getAvailableAmount()));
                accountFlowService.createBidFiledFlow(bidUserAccount, bid.getAvailableAmount());
            }
            //对账户进行统一的修改
            for (Account account : accountMap.values()) {
                accountService.update(account);
            }
            //对于借款人
            //移除借款的状态码
            UserInfo createUserUserInfo = userInfoService.get(bidRequest.getCreateUser().getId());
            createUserUserInfo.removeState(BitStateUtil.HAS_BIDREQUEST_PROCESS);
            userInfoService.update(createUserUserInfo);
            this.update(bidRequest);
        }
    }

    @Override
    public void failureOfBid(BidRequest bidRequest) {
        //借款对象和投标人对象中的借款状态改成流标
        bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_BIDDING_OVERDUE);
        bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_BIDDING_OVERDUE);
        //对于投资人
        Account bidUserAccount;
        Map<Long, Account> accountMap = new HashMap<Long, Account>();
        Long bidUserId;
        for (Bid bid : bidRequest.getBids()) {
            bidUserId = bid.getBidUser().getId();
            bidUserAccount = accountMap.get(bidUserId);
            if (bidUserAccount == null) {
                bidUserAccount = accountService.get(bid.getBidUser().getId());
                accountMap.put(bidUserId, bidUserAccount);
            }
            //可用金额增加,冻结减少,生成投标失败的流水
            bidUserAccount.setFreezedAmount(bidUserAccount.getFreezedAmount().subtract(bid.getAvailableAmount()));
            bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().add(bid.getAvailableAmount()));
            accountFlowService.createBidFiledFlow(bidUserAccount, bid.getAvailableAmount());
        }
        //对账户进行统一的修改
        for (Account account : accountMap.values()) {
            accountService.update(account);
        }
        //对于借款人
        //移除借款的状态码
        UserInfo createUserUserInfo = userInfoService.get(bidRequest.getCreateUser().getId());
        createUserUserInfo.removeState(BitStateUtil.HAS_BIDREQUEST_PROCESS);
        userInfoService.update(createUserUserInfo);
        this.update(bidRequest);
    }

    @Override
    public void audit2(Long id, Integer state, String remark) {
        //根据id获取借款对象
        BidRequest bidRequest = this.get(id);
        //判断借款对象是否为空,处于满标二审状态
        if (bidRequest != null && bidRequest.getBidRequestState() == Constants.BIDREQUEST_STATE_APPROVE_PENDING_2) {
            //生成审核历史对象
            createBidRequestAuditHistory(state,remark,bidRequest,BidRequestAuditHistory.TYPE_AUDIT2);
            //审核通过
            if (state == BidRequestAuditHistory.STATE_PASS) {
                //借款对象和投标对象的借款状态修改成还款中
                bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_PAYING_BACK);
                bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_PAYING_BACK);

                //借款人
                Account createUserAccount = accountService.get(bidRequest.getCreateUser().getId());
                //可用金额增加,剩余授信额度减少,代还本息增加,生成借款成功的流水
                createUserAccount.setUsableAmount(createUserAccount.getUsableAmount().add(bidRequest.getBidRequestAmount()));
                createUserAccount.setRemainBorrowLimit(createUserAccount.getRemainBorrowLimit().subtract(bidRequest.getBidRequestAmount()));
                //原来的代还本息+借款金额+借款总利息
                createUserAccount.setUnReturnAmount(createUserAccount.getUnReturnAmount().add(bidRequest.getBidRequestAmount().add(bidRequest.getTotalRewardAmount())));
                accountFlowService.createBorrowSuccessFlow(createUserAccount, bidRequest.getBidRequestAmount());
                //借款人支付平台(3~5%)的借款手续费,借款人可用金额减少,生成支付平台借款手续费的流水
                BigDecimal accountManagementCharge = CalculatetUtil.calAccountManagementCharge(bidRequest.getBidRequestAmount());
                createUserAccount.setUsableAmount(createUserAccount.getUsableAmount().subtract(accountManagementCharge));
                accountFlowService.createPayAccountManagementChargeFlow(createUserAccount,accountManagementCharge);
                accountService.update(createUserAccount);
                //移除借款的状态码
                UserInfo createUserUserInfo = userInfoService.get(bidRequest.getCreateUser().getId());
                createUserUserInfo.removeState(BitStateUtil.HAS_BIDREQUEST_PROCESS);
                userInfoService.update(createUserUserInfo);

                //系统账户
                SystemAccount systemAccount = systemAccountService.get();
                systemAccount.setUsableAmount(systemAccount.getUsableAmount().add(accountManagementCharge));
                systemAccountService.update(systemAccount);
                //生成系统收到借款手续费的流水
                systemAccountFlowService.createReceiveAccountManagementChargeFlow(systemAccount, accountManagementCharge);

                //投标人
                //冻结金额减少,代收利息增加,代收本金增加,生成投标成功的流水
                Account bidUserAccount;
                Long bidUserId;
                Map<Long, Account> accountMap = new HashMap<Long, Account>();
                for (Bid bid : bidRequest.getBids()) {
                    bidUserId = bid.getBidUser().getId();
                    bidUserAccount = accountMap.get(bidUserId);
                    if (bidUserAccount == null) {
                        bidUserAccount = accountService.get(bidUserId);
                        accountMap.put(bidUserId, bidUserAccount);
                    }
                    bidUserAccount.setFreezedAmount(bidUserAccount.getFreezedAmount().subtract(bid.getAvailableAmount()));
                    accountFlowService.createBidSuccessFlow(bidUserAccount, bid.getAvailableAmount());
                }


                //其他处理
                //生成还款对象和还款明细对象
                List<PaymentSchedule> paymentScheduleList = createPaymentScheduleList(bidRequest);

                //每个投标人代收利息增加,代收本金增加
                for (PaymentSchedule ps : paymentScheduleList) {
                    for (PaymentScheduleDetail psd : ps.getDetails()) {
                        Account account = accountMap.get(psd.getInvestorId());
                        account.setUnReceivePrincipal(account.getUnReceivePrincipal().add(psd.getPrincipal()));
                        account.setUnReceiveInterest(account.getUnReceiveInterest().add(psd.getInterest()));
                    }
                }

                //统一更新投标人的信息
                for (Account account : accountMap.values()) {
                    accountService.update(account);
                }

            } else {
                //审核拒绝
                //借款对象和投标对象的借款状态修改成满审拒绝

                //投标人
                //遍历投标对象,找到投标人,可用金额增加,冻结金额减少,生成投标失败的流水

                //借款人
                //移除借款的状态码
                auditReject(bidRequest);
            }

            this.update(bidRequest);
        }


    }

    /**
     * 生成还款对象集合
     * @param bidRequest
     * @return
     */
    private List<PaymentSchedule> createPaymentScheduleList(BidRequest bidRequest) {
        List<PaymentSchedule> paymentScheduleList = new ArrayList<PaymentSchedule>();
        //创建还款对象,由借款周期决定
        PaymentSchedule ps;

        BigDecimal totalAmountTemp = Constants.ZERO;
        BigDecimal interestTemp = Constants.ZERO;

        for (int i = 0; i<bidRequest.getMonthes2Return();i++){
            ps = new PaymentSchedule();
            ps.setBidRequestId(bidRequest.getId()); //借款对象
            ps.setBidRequestTitle(bidRequest.getTitle()); //借款标题
            ps.setBidRequestType(bidRequest.getBidRequestType()); //借款类型(信用标)
            ps.setBorrowUser(bidRequest.getCreateUser());//借款人
            ps.setDeadLine(DateUtils.addMonths(bidRequest.getPublishTime(),i+1));
            ps.setMonthIndex(i+1); //第几期还款(第几个月)
            ps.setReturnType(bidRequest.getReturnType());//还款类型(按月分期)
            //判断是否是最后一个还款周期
            if (i<bidRequest.getMonthes2Return()-1){
                //不是最后一个还款周期
                //还款金额:
                ps.setTotalAmount(CalculatetUtil.calMonthToReturnMoney(bidRequest.getReturnType(),bidRequest.getBidRequestAmount(),bidRequest.getCurrentRate(),i+1,bidRequest.getMonthes2Return()));
                //还款利息:
                ps.setInterest(CalculatetUtil.calMonthlyInterest(bidRequest.getReturnType(),bidRequest.getBidRequestAmount(),bidRequest.getCurrentRate(),i+1,bidRequest.getMonthes2Return()));
                //还款本金:
                ps.setPrincipal(ps.getTotalAmount().subtract(ps.getInterest()));
                totalAmountTemp = totalAmountTemp.add(ps.getTotalAmount());
                interestTemp = interestTemp.add(ps.getInterest());
            } else {
                //还款金额:总还款金额-前几期的还款金额之和
                ps.setTotalAmount(bidRequest.getBidRequestAmount().add(bidRequest.getTotalRewardAmount()).subtract(totalAmountTemp));
                //还款利息:总还款利息-前几期的还款利息之和
                ps.setInterest(bidRequest.getTotalRewardAmount().subtract(interestTemp));
                //还款本金:
                ps.setPrincipal(ps.getTotalAmount().subtract(ps.getInterest()));
            }
            paymentScheduleService.save(ps);
            //创建借款明细集合
            createPaymentScheduleDetailList(bidRequest,ps);
            paymentScheduleList.add(ps);
        }
        return paymentScheduleList;
    }

    /**
     * 创建还款明细集合
     * @param bidRequest
     * @param ps
     */
    private void createPaymentScheduleDetailList(BidRequest bidRequest, PaymentSchedule ps) {
        PaymentScheduleDetail psd;
        Bid bid;
        BigDecimal principalTemp = Constants.ZERO;
        BigDecimal interestTemp = Constants.ZERO;
        for (int i = 0; i < bidRequest.getBidCount(); i++){
            bid = bidRequest.getBids().get(i);
            psd = new PaymentScheduleDetail();
            //基本信息
            psd.setBidAmount(bid.getAvailableAmount()); //投标金额
            psd.setBidId(bid.getId()); //投标对象
            psd.setBidRequestId(bidRequest.getId()); //借款对象
            psd.setBorrowUser(bidRequest.getCreateUser()); //借款人
            psd.setDeadLine(ps.getDeadLine()); //还款日期
            psd.setInvestorId(bid.getBidUser().getId()); //投资人
            psd.setMonthIndex(ps.getMonthIndex()); //第几个月还款
            psd.setPaymentScheduleId(ps.getId()); //还款对象Id
            psd.setReturnType(bidRequest.getReturnType()); //还款类型
            //是否是最后一个还款人投标
            if (i < bidRequest.getBidCount() - 1){
                //不是
                BigDecimal rate = bid.getAvailableAmount().divide(bidRequest.getBidRequestAmount(),Constants.SCALE_CAL,RoundingMode.HALF_UP);
                //还款明细本金:(投标金额/借款金额)*还款的本金    保留四位小数
                psd.setPrincipal(rate.multiply(ps.getPrincipal()).setScale(Constants.SCALE_STORE,RoundingMode.HALF_UP));
                //还款明细利息:(投标金额/借款金额)*还款的利息
                psd.setInterest(ps.getInterest().multiply(rate).setScale(Constants.SCALE_STORE,RoundingMode.HALF_UP));
                //还款明细总金额:还款明细本金+还款明细利息
                psd.setTotalAmount(psd.getPrincipal().add(psd.getInterest()));
                principalTemp = principalTemp.add(psd.getPrincipal());
                interestTemp = interestTemp.add(psd.getInterest());
            } else {
                //还款明细本金:还款的本金-之前之和
                //还款明细利息:还款的利息-之前之和
                //还款明细总金额:还款明细本金+还款明细利息
                psd.setPrincipal(ps.getPrincipal().subtract(principalTemp));
                psd.setInterest(ps.getInterest().subtract(interestTemp));
                psd.setTotalAmount(psd.getPrincipal().add(psd.getInterest()));
            }
            paymentScheduleDetailService.save(psd);
            ps.getDetails().add(psd);
        }
    }
}
